#!/usr/bin/perl

package Swignition::Export::Recording;
use Swignition::Export;
use Swignition::Export::Contact;
use MIME::Base64;
use POSIX;

sub is
{
	my $subject = shift;
	return unless ($subject);
	return unless (ref $subject eq 'Swignition::RDFModel::Subject');	
	return
		unless (defined $subject->property('http://www.w3.org/1999/02/22-rdf-syntax-ns#type'));
	foreach my $Type ( @{$subject
		->property('http://www.w3.org/1999/02/22-rdf-syntax-ns#type')
		->valObjects} )
	{
		my $type = $Type->toString;
		return 1
			if ($type eq 'http://purl.org/media/audio#Recording'
			||  $type eq 'http://purl.org/media/audio#Album'
			||  $type eq 'http://purl.org/ontology/mo/Recording'
			||  $type eq 'http://purl.org/ontology/mo/Track'
			||  $type eq 'http://purl.org/ontology/mo/Record');
	}
	return;
}

sub outputs
{
	return [
		{
			code  => 'M3U',
			name  => 'M3U Playlist',
			type  => 'text/x-m3u',
			multi => 1
		}
	];
}

sub outM3U
{
	return "#EXTM3U\r\n"
		. "# Playlist created by Swignition.\r\n"
		. _outM3U(@_);
}

sub multiM3U
{
	my $triples = shift;
	my $rv = '';

	my $export_these = {};
	foreach my $s (keys %$triples)
	{
		$export_these->{$s} = 1
			if (defined $triples->{$s} && is($triples->{$s}));
	}
	
	foreach my $s (keys %$export_these)
	{
		my $S = findSubject($triples, $s);
		my @items = allOfObj($S, 'http://purl.org/media#contains',
		                         'http://purl.org/ontology/mo/track');
		foreach my $i (@items)
		{
			next unless $i->type;
			$export_these->{$i->toString} = 0;
		}
	}

	foreach my $s (keys %$export_these)
	{
		$rv .= _outM3U($triples, $s)
			if $export_these->{$s};
	}

	return "#EXTM3U\r\n"
		. "# Playlist created by Swignition.\r\n"
		. $rv;
}

sub _outM3U
{
	my $triples = shift;
	my $subject = shift;
	my $S = findSubject($triples, $subject);
	
	my $rv;

	# Summary
	my $title = firstOfLiteral($S,
		['http://purl.org/dc/terms/title',
		'http://purl.org/dc/elements/1.1/title'],
		['http://www.w3.org/1999/02/22-rdf-syntax-ns#value']);

	# Duration
	my $duration = firstOfLiteral($S,
		['http://purl.org/media#duration'],
		['http://www.w3.org/1999/02/22-rdf-syntax-ns#value']);
	$duration =~ s/\,/\./g;

	# Download
	my $download = firstOf($S,
		'http://purl.org/media#download',
		'http://purl.org/ontology/mo/item',
		'http://purl.org/ontology/mo/available_as');
	if ($download)
	{
		my $D       = findSubject($triples, $download);
		my @formats = allOfObj($D, 'http://purl.org/dc/terms/format');
		my $format_ok;
			
		foreach my $f (@formats)
		{
			last if (defined $format_ok);
			next unless ($f->vocab eq 'http://purl.org/dc/terms/IMT');
			if ($f->toString =~ m#(application/ogg|audio/.+)#)
				{ $format_ok = 1; }
			else
				{ $format_ok = -1; }
		}
	
		$download = undef if ($format_ok == -1);
	}
	
	if ($download)
	{
		my $duration_s;
		if ($duration =~ /^
						\-?                  # Potentially negitive...
						P                    # Period of...
						(?:([\d\,\.]+)Y)?    # n Years
						(?:([\d\,\.]+)M)?    # n Months
						(?:([\d\,\.]+)W)?    # n Weeks
						(?:([\d\,\.]+)D)?    # n Days
						(?:                 
							T                 # And a time of...
							(?:([\d\,\.]+)H)? # n Hours
							(?:([\d\,\.]+)M)? # n Minutes
							(?:([\d\,\.]+)S)? # n Seconds
						)?
						/x)
		{
			$duration_s = (365 * 24 * 3600 * $1)
							+ (30 * 24 * 3600 * $2)
							+ (7 * 24 * 3600 * $3)
							+ (24 * 3600 * $4)
							+ (3600 * $5)
							+ (60 * $6)
							+ $7;
			$duration_s *= -1 if ($duration =~ /^\-/);
		}
		else
		{
			$duration_s = -1;
		}
		
		$rv = "#EXTINF:$duration_s,$title\r\n"
			."$download\r\n";		
	}
	
	my @items = allOfObj($S, 'http://purl.org/media#contains', 'http://purl.org/ontology/mo/track');
	if (@items)
	{
		my $ordered_items = {};
		foreach my $item (@items)
		{
			next unless ($item->type);
			my $iSubject = findSubject($triples, $item->toString);
			my $position = firstOfLiteral($iSubject,
				['http://purl.org/media#position'],
				['http://www.w3.org/1999/02/22-rdf-syntax-ns#value']);
			$position = POSIX::floor($position);
			push @{ $ordered_items->{$position} }, $item;
		}
		foreach my $position (sort keys %$ordered_items)
		{
			foreach my $item (@{ $ordered_items->{$position} })
			{
				$rv .= _outM3U($triples, $item->toString);
			}
		}
	}
	
	return $rv;
}

1;
